﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web;

namespace NRemedy.MVC.UI
{
    //考虑支持两种类型的表格：
    //1、基于remedy表单和model的表格
        //数据要素：
        //1、模型类型（表单名）
        //2、列字段
        //3、额外属性和选项
    //2、基于非remedy表单和model的表格，暂时不实现
    public class NRemedyGrid<TModel>
    {
        protected object _tablehtmlAttribute;
        protected object _optionAttribute;
        protected object _eventChainCallback;
        protected string _qulification;
       
        private DefaultTypeMetaProvider<TModel> provider;
        private List<NRemedyGridColumn<TModel>> Columns = new List<NRemedyGridColumn<TModel>>();
        private IEnumerable<PropertyAndField<TModel>> _properties;

        public NRemedyGrid(object htmlAttribute, object optionAttribute, object eventChainCallback)
        {
            _tablehtmlAttribute = htmlAttribute;
            _optionAttribute = optionAttribute;
            _eventChainCallback = eventChainCallback;
            this.provider = new DefaultTypeMetaProvider<TModel>();
            _properties = provider.GetPropertyInfoes(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, null);
        }

        public NRemedyGrid():
            this(null,null,null)
        {
 
        }

        public NRemedyGrid(object htmlAttribute, object optionAttribute) :
            this(htmlAttribute, optionAttribute, null)
        {

        }

        protected virtual string GetTableUrl()
        {
            return "/Table/Query/" + provider.GetFormNameFromModelType();
        }

        public virtual NRemedyGrid<TModel> Column<TValue>(Expression<Func<TModel, TValue>> columnSelector, string title, object htmlAttribute, object optionAttribute, object eventChainCallback)
        {
            string propertyName = ExpressionHelper.GetExpressionText(columnSelector);
            var tp = _properties.FirstOrDefault(p => p.Property.Name == propertyName);
            if (tp != null)
            {
                NRemedyGridColumn<TModel> column = new NRemedyGridColumn<TModel>(tp.DatabaseId.ToString(), title, htmlAttribute, optionAttribute);
                Columns.Add(column);
            }
            return this;
        }

        public virtual NRemedyGrid<TModel> Column<TValue>(Expression<Func<TModel, TValue>> columnSelector, string title, object htmlAttribute, object optionAttribute)
        {
            return Column<TValue>(columnSelector, title, htmlAttribute, optionAttribute, null/* eventChainCallback */);
        }

        public virtual NRemedyGrid<TModel> Column<TValue>(Expression<Func<TModel, TValue>> columnSelector, string title)
        {
            return Column<TValue>(columnSelector, title, null, null, null/* eventChainCallback */);
        }

        public virtual NRemedyGrid<TModel> Qulification(string qulification)
        {
            this._qulification = qulification;
            return this;
        }

        public virtual MvcHtmlString GetHtml()
        {
            RawTagBuilder tagb = new RawTagBuilder("table");
            tagb.AddCssClass("easyui-datagrid");

            DataOptionBuilder dob = new DataOptionBuilder();
            dob.MergeAttribute("url", GetTableUrl());

            //queryParams:{fields:||||}
            if (Columns.Count > 0){
                string fields = string.Empty;
                foreach (var property in _properties)
                {
                    if (Columns.FirstOrDefault(m => m.propertyId == property.DatabaseId.ToString()) != null)
                    {
                        fields += property.DatabaseId + "|";
                    }
                }

                fields = "{ fields:'" + fields.TrimEnd('|') + "' }";

                dob.MergeObject("queryParams", fields);

            }


            var callback = HtmlHelper.AnonymousObjectToHtmlAttributes(_eventChainCallback);

            string defaultBeforeLoad = string.Empty;
            if (!string.IsNullOrEmpty(this._qulification))
                defaultBeforeLoad += "rebuildTableParam($(this),param);";
            if (callback.ContainsKey("onBeforeLoad"))
                defaultBeforeLoad += "return " + callback["onBeforeLoad"] + "($(this),param);";
            if (defaultBeforeLoad != string.Empty)
            {
                dob.MergeCallback("onBeforeLoad", "function(param){ " + defaultBeforeLoad + " }");
            }


            if (_optionAttribute != null)
            {
                var option_dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(_optionAttribute);
                foreach (var option in option_dictionary)
                {
                    dob.MergeAttribute(option.Key, option.Value.ToString());
                }
            }

            tagb.MergeAttribute("data-options", dob.ToString());

            if (_tablehtmlAttribute != null)
            {
                var html_dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(_tablehtmlAttribute);
                if (!string.IsNullOrEmpty(_qulification)){
                    html_dictionary["qualification"] = _qulification;
                }

                foreach (var h in html_dictionary)
                {
                    string value = HttpUtility.HtmlAttributeEncode(h.Value.ToString());
                    tagb.MergeAttribute(h.Key, value);
                }
            }

            TagBuilder thead = new TagBuilder("thead");

            StringBuilder Table = new StringBuilder(tagb.ToString(TagRenderMode.StartTag));
            Table.Append(thead.ToString(TagRenderMode.StartTag));
            Columns.ForEach(c => Table.Append(c.GetHtml()));
            Table.Append(thead.ToString(TagRenderMode.EndTag));
            Table.Append(tagb.ToString(TagRenderMode.EndTag));
            return MvcHtmlString.Create(Table.ToString());
        }
    }
}
